/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package xmarti.vacaxm.utils;

import java.awt.Rectangle;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
import javax.swing.RowSorter;
import javax.swing.event.ListSelectionEvent;
import xmarti.vacaxm.action.ImplSequence;
import xmarti.vacaxm.exception.ExceptionHibernateVacaxm;
import xmarti.vacaxm.format.Format;
import xmarti.vacaxm.format.FormatJSplitPane;

/**
 * ABSTRACT CLASS AbstractDialog. 
 * Representa el motor o esquelet, les accions, operacions i representacions 
 * gràfiques que són comunes en un formulari tipus diàleg de VacaXM. 
 * 
 * Representacions comunes tals com, una taula amb dos columnes (codi i 
 * descripció), un panel per representar una fila de la taula per poder 
 * modificar els dos atributs (columnes).
 * 
 * Accions comunes tals com, escoltador, ordenació i selecció  de la taula. 
 * Carregar, afegir, modificar i eliminar objectes. Així com persistir-los.
 * 
 * Operacions de control i representació dels diferents atributs. Aquestes 
 * són assistides per classes externes: formatJSplitPane (per poder guardar la 
 * configuració i disposició dels diferents elements).
 * 
 * @author xmarti
 */
public abstract class AbstractDialog {
    /**
     * Taula on es visualitzen els registres
     */
    private JTableXM jTableStates;  //Taula on es visualitzen els registres
    private TableModel model;
    private ImplSequence aSequence; 
    private boolean insert;
    private ListSelectionModel selectionModel=null;
    private List<RowSorter.SortKey> orderTable=null;
    private FormatJSplitPane fJsplit;
    private boolean isSaved=true; 
    private String path;    
    private JPanel jPanelObject;
    private JLabel jLabelAction;
    private Object object;
    /**
     * CONSTRUCTOR de AbstractDialog
     * @param path Nom del Fitxer XML 
     * @param jPaneObject Panel Contenidor
     * @param jLabelAction  
     * 
     */
    public AbstractDialog(String path,JPanel jPaneObject, JLabel jLabelAction){
        this.fJsplit  = new FormatJSplitPane();  
        this.jPanelObject=jPaneObject;
        this.jLabelAction= jLabelAction;        
        this.jTableStates= new JTableXM() {
            @Override
            public void handleSelectionEvent(ListSelectionEvent e) {
               selectionEvent(e);
            }
        };
        this.path=path;
    }
    /**
     *  Selection Event. Quan es selecciona un registre de la taula. 
     *  1) comprova si l'objecte anterior ha estat manipulat. Si es així demana
     *      a l'usuari si vol guardar-lo. 
     *      1.1) el guarda l'anterior i carrega el següent (el seleccionat).
     *      
     * @param e  Disparador
     */
    private void selectionEvent(ListSelectionEvent e){
        if(this.jTableStates.getSelectedRow()>-1){ // comprova que s'ha seleccionat una fila de la taula                                              
                if(!this.isSaved){ //comprova si el objecte actual ha estat guardat.
                    isSaved=true;  //el marca com guardat idependentment de si es realitza l'acció o no
                    
                    // demana permís per guardar els canvis realitats
                    if(Utils.confirmSaveOptionPane(TDSLanguageUtils.getMessage("jDialogSequenceType.confirm.save.caption"))==0) {                      
                        Object objectNext =(Object) this.jTableStates.getValueAt(this.jTableStates.getSelectedRow(),0); 
                        try{
                        saveData(); //guarda l'objecte
                        selectData(objectNext); //selecciona l'objecte seleccionat a la taula
                        this.object=objectNext; // el passa com actual
                            getFormat(); // aplica el format corresponen
                        } catch (ExceptionHibernateVacaxm ex) {
                            if (this.insert){
                                this.jLabelAction.setText(EnumAction.NO_INSERT.getAction());
                            }else{
                                this.jLabelAction.setText(EnumAction.NO_UPDATE.getAction());                
                            }
                            JOptionPane.showMessageDialog(null,ex.getMessage() ,TDSLanguageUtils.getMessage("save.data.ERR"),JOptionPane.ERROR_MESSAGE);
                        }
                    }else{ // carrega l'objecte seleccionat a ala taula
                        this.object=(Object) this.jTableStates.getValueAt(this.jTableStates.getSelectedRow(),0); 
                    }
                }else{// carrega l'objecte seleccionat a la taula
                      this.object=(Object) this.jTableStates.getValueAt(this.jTableStates.getSelectedRow(),0); 
                }
                
                if (this.object.toString()==null) { // comprova si es una inserció
                    this.insert=true;  
                    this.jLabelAction.setText(EnumAction.INSERT.getAction());
                    
                } else{ // en cas contrari es una modificació
                    this.jPanelObject.setBorder(javax.swing.BorderFactory.createTitledBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 1, true),TDSLanguageUtils.getMessage("jDialogState.JPanelState.update.caption")+this.object.toString()));
                    this.jLabelAction.setText(EnumAction.UPDATE.getAction());
                    this.insert=false;                     
                }                
                setData(); //carrega les dades i mou la posició de la taula per visualtizar el registre seleccionat
                this.jTableStates.scrollRectToVisible(new Rectangle(this.jTableStates.getCellRect(this.jTableStates.getSelectedRow(), 0, true)));                                                   
                enabledObjects(true);
            }
    }
    
    private void getFormat(){ //recupera el format predeterminat
        Format format= new Format();
        this.fJsplit  = new FormatJSplitPane();       
        try {
            this.fJsplit= format.read (this.path);
            for (int i =0; i< this.fJsplit.getCols().size();i++){
                this.jTableStates.getColumnModel().getColumn(i).setPreferredWidth( fJsplit.getCol(i));                                                       
            }
            
        } catch (Exception ex) {
            setFormat(); // en cas d'excepció força la vista actual i la guarda.
        }        
    }    
     private void setFormat(){ // guarda la vista actual.
       Format format= new Format(); 
       this.fJsplit= new FormatJSplitPane();
       for (int i =0; i< jTableStates.getColumnModel().getColumnCount();i++){
           this.fJsplit.setCol(jTableStates.getColumnModel().getColumn(i).getWidth());
       }       
        try {
            format.write(this.path, this.fJsplit);
        } catch (Exception ex) {            
           JOptionPane.showMessageDialog(null,ex.getMessage(),TDSLanguageUtils.getMessage("charge.xml.ERR"),JOptionPane.ERROR_MESSAGE);
        }
    }    
    /**
     * Guarda l'objecte actual
     * @param object Objecte a guardar
     * @throws ExceptionHibernateVacaxm 
     */
    private void jButtonSaved(Object object) throws ExceptionHibernateVacaxm {                                                        
        saveData();           
        selectData(object);
        getFormat();
        this.isSaved=true;
    }   
    /**
     * Accessor de lectura
     * @return 
     */
    public Object getObject() {
        return object;
    }
    /**
     * Accesor d'escriptura
     * @param object 
     */
    public void setObject(Object object) {
        this.object = object;
    }
    /**
     * Operacions abastractes per tal de tractar les dades
     */
    abstract void getData();
    abstract void setData();
    abstract void enabledObjects(boolean modify);
    abstract void saveData()throws ExceptionHibernateVacaxm;
    abstract void selectData(Object object);
    abstract TableModel getModel() throws ExceptionHibernateVacaxm;
    
}
